package vip.zhenzicheng.jpa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzc.zfast.web.domain.PageResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import vip.zhenzicheng.jpa.base.BaseServiceImpl;
import vip.zhenzicheng.jpa.domain.dto.StudentDTO;
import vip.zhenzicheng.jpa.domain.entity.Student;
import vip.zhenzicheng.jpa.domain.entity.User;
import vip.zhenzicheng.jpa.domain.vo.StudentVO;
import vip.zhenzicheng.jpa.repository.StudentRepository;
import vip.zhenzicheng.jpa.service.StudentService;

import javax.annotation.Resource;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zhenzicheng
 * @date 2023-04-17 16:27
 */
@Service
public class StudentServiceImpl extends BaseServiceImpl<Student, Integer> implements StudentService {

    @Resource
    StudentRepository studentRepository;


    @Override
    protected JpaRepository<Student, Integer> getRepository() {
        return this.studentRepository;
    }

    @Override
    public PageResult<StudentVO> findAll(StudentDTO dto) {
        PageRequest pageRequest = PageRequest.of(dto.getCurrent(), dto.getSize());
        // 模糊查询
        // Specification<Student> studentSpec = getStudentSpecification(dto);

        Specification<Student> studentSpec = (root, query, criteriaBuilder) -> criteriaBuilder.and(
                criteriaBuilder.like(root.get("user").get("nickName"), "%" + dto.getNickName() + "%"));

        Page<Student> studentPage = studentRepository.findAll(studentSpec, pageRequest);
        if (studentPage.getTotalElements() > 0) {
            List<StudentVO> vos = studentPage.getContent().stream().map(stu -> {
                StudentVO vo = new StudentVO();
                if (Objects.nonNull(stu.getUser())) {
                    BeanUtil.copyProperties(stu.getUser(), vo);
                    vo.setUserId(stu.getUser().getId());
                }
                vo.setStudentId(stu.getId());
                return vo;
            }).collect(Collectors.toList());
            return PageResult.pageOf(vos, studentPage.getTotalElements(), dto.getSize(), dto.getCurrent());
        }

        return PageResult.pageOf(Collections.emptyList(), 0, dto.getSize(), dto.getCurrent());
    }

    private Specification<Student> getStudentSpecification(StudentDTO dto) {
        List<Predicate> predicates = new ArrayList<>();
        return (root, query, criteriaBuilder) -> {
            Path<User> userPath = root.get("user");

            // 昵称模糊查询
            if (StringUtils.hasLength(dto.getNickName())) {
                predicates.add(criteriaBuilder.like(userPath.get("nickName"), "%" + dto.getNickName() + "%"));
            }
            // 用户名模糊查询
            if (StringUtils.hasLength(dto.getUsername())) {
                predicates.add(criteriaBuilder.like(root.get("user").get("username"), "%" + dto.getUsername() + "%"));
            }
            // 年龄区间查询
            if (StringUtils.hasLength(dto.getAgeRange())) {
                String[] ageRanges = dto.getAgeRange().split(",");
                predicates.add(criteriaBuilder.ge(root.get("user").get("age"), Integer.parseInt(ageRanges[0])));
                if (ageRanges.length > 1) {
                    predicates.add(criteriaBuilder.lt(root.get("user").get("age"), Integer.parseInt(ageRanges[1])));
                }
            }
            // 性别
            if (dto.getSex() != null) {
                predicates.add(criteriaBuilder.equal(root.get("user").get("sex"), dto.getSex()));
            }

            // 批量使用刚才的条件断言
            // return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
            return query.where(predicates.toArray(new Predicate[0])).getRestriction();
        };
    }
}
